package com.wuba.baojie.service.impl;


import com.alibaba.fastjson.JSON;
import com.wuba.baojie.config.DistanceUtil;
import com.wuba.baojie.config.FileUtils;
import com.wuba.baojie.config.WeChatUtils;
import com.wuba.baojie.controller.SignListVo;
import com.wuba.baojie.dto.*;
import com.wuba.baojie.mapper.*;
import com.wuba.baojie.pojo.*;
import com.wuba.baojie.vo.ApplyListVo;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.AlgorithmParameters;

import java.security.Security;
import com.alibaba.fastjson.JSONObject;
import com.wuba.baojie.enums.StatusEnums;
import com.wuba.baojie.service.WeChatService;
import com.wuba.baojie.vo.AccessTokenDto;
import com.wuba.baojie.vo.LoginDto;
import com.wuba.baojie.vo.LoginVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Author: Eric.zhou
 * @Date: 2019/6/3 14:38
 */
@Service
public class WeChatServiceImpl implements WeChatService {

    private RestTemplate httpRest = new RestTemplate();
    @Value("${wechat.appId}")
    private String appid;
    @Value("${wechat.secret}")
    private String secret;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SignMapper signMapper;
    @Autowired
    private LocalMapper localMapper;
    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private ApplyMapper applyMapper;

    /**
     * 微信登录
     *
     * @param code
     * @return
     */
    @Override
    public LoginVo weChatLogin(String code) throws Exception {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=wx709d3076ad5fe531&secret=f155a61f1c721f946e9711f94fe87118&js_code=" + code + "&grant_type=authorization_code";
        ResponseEntity<String> forObject = httpRest.getForEntity(url, String.class);
//        LoginDto parse = (LoginDto) JSONObject.parse(forObject.getBody());
        LoginDto stu = (LoginDto) JSONObject.parseObject(forObject.getBody(), LoginDto.class);
//            if (stu.ge)
//        WeChatUser weChatUser = wechatUserMapper.selectByOpenId(stu.getOpenid());
//        if (weChatUser == null) {
//            WeChatUser wechatUser = new WeChatUser();
//            wechatUser.setAddTime(new Date());
//            wechatUser.setLoginTime(new Date());
//            wechatUser.setStatus(StatusEnums.YES.getEcode());
//            wechatUser.setMessageSwitch(StatusEnums.NO.getEcode());
//            wechatUser.setWechatSwitch(StatusEnums.YES.getEcode());
//            wechatUser.setOpenId(stu.getOpenid());
//            wechatUserMapper.insertSelective(wechatUser);
//        } else if (weChatUser.getStatus().equals(StatusEnums.NO.getEcode())) {
//            throw new Exception("账户已被冻结");
//        }
        UserExample userExample = new UserExample();
//        userExample.createCriteria().andOpenIdEqualTo()
//        userMapper.selectByExample()
        LoginVo vo = new LoginVo();
        vo.setRegister(Boolean.FALSE);
//        userMapper.selectByExample()
//        if (weChatUser.getCloum3()!=null&&weChatUser.getCloum4()!=null){
//            vo.setRegister(Boolean.TRUE);
//        }
        vo.setOpenId(stu.getOpenid());
        vo.setSessionKey(stu.getSession_key());


        return vo;
    }

    /**
     * 签到
     *
     * @param signDto
     */
    @Override
    public int sign(SignDto signDto) throws Exception {
        System.out.println(JSONObject.toJSON(signDto).toString());
        Boolean flag = false;
        List<Local> locals = localMapper.selectByExample(new LocalExample());
        for (Local local : locals) {
            double distance = DistanceUtil.getDistance(Double.valueOf(signDto.getLongit()), Double.valueOf(signDto.getLat()), Double.valueOf(local.getLng()), Double.valueOf(local.getLat()));
            //如果小于500米签到成功 否则 失败
            if (distance<=500.00){
                flag = Boolean.TRUE;

            }
        }
        if (!flag){
            throw new Exception("没到打卡点,无法打卡");
        }
        Sign sign = new Sign();
        sign.setAddTime(new Date());
        sign.setLat(signDto.getLat());
        sign.setLng(signDto.getLongit());
        sign.setOpenId(signDto.getOpenId());
        sign.setLocal(locals.get(0).getId());
        signMapper.insert(sign);
        System.out.println(signDto.toString());
        LocalDateTime endLoc = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        LocalDateTime startLoc = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = endLoc.atZone(zoneId);//Combines this date-time with a time-zone to create a  ZonedDateTime.
        ZonedDateTime szdt = startLoc.atZone(zoneId);//Combines this date-time with a time-zone to create a  ZonedDateTime.
        Date endDate = Date.from(zdt.toInstant());
        Date startDate = Date.from(szdt.toInstant());
        SignExample example = new SignExample();
        example.createCriteria().andOpenIdEqualTo(signDto.getOpenId()).andAddTimeBetween(startDate,endDate);
        List<Sign> signs = signMapper.selectByExample(example);
        return signs.size();

    }

    /**
     * 获取积分
     *
     * @param scoringDto
     */
    @Override
    public void scoring(ScoringDto scoringDto) {
        UserExample example = new UserExample();
        example.createCriteria().andOpenIdEqualTo(scoringDto.getOpenId());

        List<User> users = userMapper.selectByExample(example);
        if (users.size()>0){
            User user = users.get(0);
            if (user.getVideo().equals(0)){
                user.setScore(user.getScore()+100);
                userMapper.updateByPrimaryKeySelective(user);
            }
        }
        System.out.println(scoringDto.toString());
    }

    /**
     * 获取微信调用权限
     *
     * @return
     */
    public String getAccessToken() {
        String secret = "f155a61f1c721f946e9711f94fe87118";
        //获取access_token
//        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
//                "&appid=" + appid + "&secret=" + secret;
//        String json = restTemplate.getForObject(url, String.class);
//        String accessToken = stringRedisTemplate.opsForValue().get("accessToken");
        AccessTokenDto forObject = httpRest.getForObject("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret, AccessTokenDto.class);
        return forObject.getAccess_token();
    }







    public static String decrypt(byte[] key, byte[] iv, byte[] encData) throws Exception {
        AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        //解析解密后的字符串  
        return new String(cipher.doFinal(encData), "UTF-8");
    }


    public Object getPhoneNumber(PhoneNumberDto phoneNumberDto) {
        // 被加密的数据
        byte[] dataByte = Base64.decode(phoneNumberDto.getEncryptedData());        // 加密秘钥
        byte[] keyByte = Base64.decode(phoneNumberDto.getSession_key());
        // 偏移量
        byte[] ivByte = Base64.decode(phoneNumberDto.getIv());
        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                JSONObject jsonObject = JSONObject.parseObject(result);
                String phoneNumber = (String) jsonObject.get("phoneNumber");
                User user = userMapper.selectByPhone(phoneNumber);
                if (user!=null){
                    user.setOpenId(phoneNumberDto.getOpenId());
                    userMapper.updateByPrimaryKeySelective(user);
                }else {
                    User newUser = new User();
                    newUser.setPhone(phoneNumber);
                    newUser.setOpenId(phoneNumberDto.getOpenId());
                    newUser.setVideo(1);
                    newUser.setScore(0);
                    userMapper.insertSelective(user);
                }
                return JSONObject.parseObject(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取视频地址
     * @param videoDto
     * @return
     */
    @Override
    public String getVideo(VideoDto videoDto) {
        UserExample example = new UserExample();
        example.createCriteria().andOpenIdEqualTo(videoDto.getOpenId()).andPhoneEqualTo(videoDto.getPhone());
        List<User> users = userMapper.selectByExample(example);
        if (users.size()>0){
            User user = users.get(0);
            if (user.getVideo()==0){
                List<Video> videos = videoMapper.selectByExampleWithBLOBs(new VideoExample());
//                return "http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400%22";
           return videos.get(0).getPath();
            }else {
                return "http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400%22";
            }
        }
        return "http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400%22";
    }

    @Override
    public String joinCode(String sencen, HttpServletRequest request) throws IOException {
        try {
            RestTemplate rest = new RestTemplate();
            InputStream inputStream = null;
            OutputStream outputStream = null;
            try {
                String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+getAccessToken();
                Map<String,Object> param = new HashMap<>();
                param.put("scene", sencen);
                param.put("page", "pages/index/index");
                param.put("width", 430);
//                param.put("auto_color", false);
//                Map<String,Object> line_color = new HashMap<>();
//                line_color.put("r", 0);
//                line_color.put("g", 0);
//                line_color.put("b", 0);
//                param.put("line_color", line_color);
               System.out.println("调用生成微信URL接口传参:" + param);
                MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
                HttpEntity requestEntity = new HttpEntity(param, headers);
                ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
               System.out.println("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());
                byte[] result = entity.getBody();
               System.out.println(Base64.encode(result));
                inputStream = new ByteArrayInputStream(result);

                File file = new File("C:\\Users\\Admin\\Desktop\\"+sencen+".png");
                if (!file.exists()){
                    file.createNewFile();
                }
                outputStream = new FileOutputStream(file);
                int len = 0;
                byte[] buf = new byte[1024];
                while ((len = inputStream.read(buf, 0, 1024)) != -1) {
                    outputStream.write(buf, 0, len);
                }
                outputStream.flush();
            } catch (Exception e) {
//                LOG.error("调用小程序生成微信永久小程序码URL接口异常",e);
            } finally {
                if(inputStream != null){
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(outputStream != null){
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return null;    
        } catch (Exception e) {
            throw e;
        }
    }













    /**
     * 将二进制转换成文件保存
     * @param instreams 二进制流
     * @param imgPath 图片的保存路径
     * @param imgName 图片的名称
     * @return
     *      1：保存正常
     *      0：保存失败
     */
    public static int saveToImgByInputStream(InputStream instreams,String imgPath,String imgName){
        int stateInt = 1;
        if(instreams != null){
            try {
                File file=new File(imgPath,imgName);//可以是任何图片格式.jpg,.png等
                FileOutputStream fos=new FileOutputStream(file);
                byte[] b = new byte[1024];
                int nRead = 0;
                while ((nRead = instreams.read(b)) != -1) {
                    fos.write(b, 0, nRead);
                }
                fos.flush();
                fos.close();
            } catch (Exception e) {
                stateInt = 0;
                e.printStackTrace();
            } finally {
            }
        }
        return stateInt;
    }

//    /**
//     * 小程序接口
//     * @author 0200759
//     *
//     */
//    @Controller
//    @RequestMapping("/applet")
//    public class AppletController {


        /**
         * @param res
         * 调用二维码接口2(https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN)
         */
//        @RequestMapping("/getQRCode")
        public void getQRCode(HttpServletResponse res,String sences) throws Exception {
            RestTemplate rest = new RestTemplate();
            InputStream inputStream = null;
            try {
//                AppletTokenResult appletTokenResult = CacheAppletUtil.get(Constants.APPLET_TOKEN);
//                if(appletTokenResult == null || StringUtil.isEmpty(appletTokenResult.getAccess_token())){
//                    throw new CommonException("小程序token获取失败！");
//                }
                String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="
                        +getAccessToken();
                Map<String, Object> param= new HashMap<String, Object>();
                param.put("scene", sences);
                param.put("path", "pages/index");
                param.put("width", 430);
                param.put("auto_color", false);
                Map<String,Object> line_color = new HashMap<>();
                line_color.put("r", 0);
                line_color.put("g", 0);
                line_color.put("b", 0);
                param.put("line_color", line_color);
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
//                HttpEntity<String> requestEntity = new HttpEntity<String>(new Gson().toJson(param), headers);
                HttpEntity<String> requestEntity = new HttpEntity<String>(JSON.toJSONString(param), headers);
                ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST,
                        requestEntity, byte[].class, new Object[0]);
                byte[] result = entity.getBody();
                inputStream = new ByteArrayInputStream(result);

                IOUtils.copy(inputStream, res.getOutputStream());

            } catch (Exception e) {
              throw  new Exception("调用小程序生成微信永久小程序码URL接口异常!");
            } finally {
                if(inputStream != null){
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    @Override
    public List<SignListVo> signList(String start, String end) {
        List<SignListVo> voList =new ArrayList<>();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate startparse = LocalDate.parse(start, dtf);
        LocalDate endparse = LocalDate.parse(end, dtf);
        LocalDateTime endLoc = LocalDateTime.of(endparse, LocalTime.MAX);
        LocalDateTime startLoc = LocalDateTime.of(startparse, LocalTime.MIN);
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = endLoc.atZone(zoneId);//Combines this date-time with a time-zone to create a  ZonedDateTime.
        ZonedDateTime szdt = startLoc.atZone(zoneId);//Combines this date-time with a time-zone to create a  ZonedDateTime.
        Date endDate = Date.from(zdt.toInstant());
        Date startDate = Date.from(szdt.toInstant());
//        Date date = new Date(startLoc);
        SignExample example = new SignExample();
        example.createCriteria().andAddTimeBetween(startDate,endDate);
        List<Sign> signs = signMapper.selectByExample(example);
        for (Sign sign : signs) {
            SignListVo vo = new SignListVo();
            vo.setLocal(sign.getLocal());
            User user = userMapper.selectByOpenId(sign.getOpenId());
            vo.setPhone(user.getPhone());
            vo.setName(user.getName());
            vo.setAddTime(sign.getAddTime());
            voList.add(vo);
        }
        return voList;
    }

    /**
     * 申领
     * @param applyDto
     */
    @Override
    public void apply(ApplyDto applyDto) throws Exception {
        String openId = applyDto.getOpenId();
        User user = userMapper.selectByOpenId(openId);
        //随时上报 最后统计导出
        if (user.getName()!=null&&user.getPhone()!=null){
            ApplyExample applyExample = new ApplyExample();
            applyExample.createCriteria().andAddressEqualTo(applyDto.getAddress());
            List<Apply> applies = applyMapper.selectByExample(applyExample);
            if (applies.size()>0){
                Apply apply = applies.get(0);
                apply.setAddTime(new Date());
                apply.setBig(applyDto.getBig());
                apply.setCup(applyDto.getCup());
                apply.setMedium(applyDto.getMedium());
                apply.setNipiao(applyDto.getNipiao());
                apply.setShouzhi(applyDto.getShouzhi());
                apply.setSmall(applyDto.getSmall());
                apply.setQingfeng(applyDto.getQingfeng());
                apply.setWarter(applyDto.getWarter());
                applyMapper.updateByPrimaryKeySelective(apply);
            }else {
                Apply apply = new Apply();
                apply.setAddress(applyDto.getAddress());
                apply.setOpenId(applyDto.getOpenId());
                apply.setAddTime(new Date());
                apply.setBig(applyDto.getBig());
                apply.setCup(applyDto.getCup());
                apply.setMedium(applyDto.getMedium());
                apply.setNipiao(applyDto.getNipiao());
                apply.setShouzhi(applyDto.getShouzhi());
                apply.setSmall(applyDto.getSmall());
                apply.setQingfeng(applyDto.getQingfeng());
                apply.setWarter(applyDto.getWarter());
                applyMapper.insertSelective(apply);
            }
        }else {
            throw new Exception("你无权申领");
        }
    }

    /**
     * 申领列表
     * @param address
     * @return
     */
    @Override
    public Apply applyList(String address) {
        ApplyExample applyExample = new ApplyExample();
        applyExample.createCriteria().andAddressEqualTo(address);
        List<Apply> applies = applyMapper.selectByExample(applyExample);
        if (applies.size()>0){
            return applies.get(0);
        }
        return null;
    }

    @Override
    public List<Apply> applyLists() {
        ApplyExample applyExample = new ApplyExample();
        List<Apply> applies = applyMapper.selectByExample(applyExample);
        return applies;
    }
}


//}
